From 212241ffdad4767e5154de45c08ba3af952fedd1 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 25 Jun 2011 21:00:02 -0400 Subject: [PATCH] GtkEntryAccessible: Rework text_changed handling No more signal emission from an idle. --- gtk/a11y/gtkentryaccessible.c | 160 +++++++++++++--------------------- gtk/a11y/gtkentryaccessible.h | 5 -- 2 files changed, 63 insertions(+), 102 deletions(-) diff --git a/gtk/a11y/gtkentryaccessible.c b/gtk/a11y/gtkentryaccessible.c index ea20f48714..6132b90efe 100644 --- a/gtk/a11y/gtkentryaccessible.c +++ b/gtk/a11y/gtkentryaccessible.c @@ -28,16 +28,13 @@ /* Callbacks */ -static gboolean gtk_entry_accessible_idle_notify_insert (gpointer data); -static void gtk_entry_accessible_notify_insert (GtkEntryAccessible *entry); -static void gtk_entry_accessible_notify_delete (GtkEntryAccessible *entry); static void gtk_entry_accessible_insert_text_cb (GtkEntry *entry, - gchar *arg1, - gint arg2, - gpointer arg3); + gchar *new_text, + gint new_text_length, + gint *position); static void gtk_entry_accessible_delete_text_cb (GtkEntry *entry, - gint arg1, - gint arg2); + gint start, + gint end); static void gtk_entry_accessible_changed_cb (GtkEntry *entry); static gboolean check_for_selection_change (GtkEntryAccessible *entry, GtkEntry *gtk_entry); @@ -184,9 +181,6 @@ gtk_entry_accessible_notify_gtk (GObject *obj, if (strcmp (pspec->name, "cursor-position") == 0) { - if (entry->insert_idle_handler == 0) - entry->insert_idle_handler = gdk_threads_add_idle (gtk_entry_accessible_idle_notify_insert, entry); - if (check_for_selection_change (entry, gtk_entry)) g_signal_emit_by_name (atk_obj, "text_selection_changed"); /* @@ -197,9 +191,6 @@ gtk_entry_accessible_notify_gtk (GObject *obj, } else if (strcmp (pspec->name, "selection-bound") == 0) { - if (entry->insert_idle_handler == 0) - entry->insert_idle_handler = gdk_threads_add_idle (gtk_entry_accessible_idle_notify_insert, entry); - if (check_for_selection_change (entry, gtk_entry)) g_signal_emit_by_name (atk_obj, "text_selection_changed"); } @@ -268,8 +259,8 @@ gtk_entry_accessible_class_init (GtkEntryAccessibleClass *klass) static void gtk_entry_accessible_init (GtkEntryAccessible *entry) { - entry->signal_name_insert = NULL; - entry->signal_name_delete = NULL; + entry->length_insert = 0; + entry->length_delete = 0; entry->cursor_position = 0; entry->selection_bound = 0; entry->activate_keybinding = NULL; @@ -897,114 +888,89 @@ atk_editable_text_interface_init (AtkEditableTextIface *iface) /* Callbacks */ -static gboolean -gtk_entry_accessible_idle_notify_insert (gpointer data) -{ - GtkEntryAccessible *entry; - - entry = GTK_ENTRY_ACCESSIBLE (data); - entry->insert_idle_handler = 0; - gtk_entry_accessible_notify_insert (entry); - - return FALSE; -} - +/* We connect to GtkEditable::insert-text, since it carries + * the information we need. But we delay emitting our own + * text_changed::insert signal until the entry has update + * all its internal state and emits GtkEntry::changed. + */ static void -gtk_entry_accessible_notify_insert (GtkEntryAccessible *entry) +gtk_entry_accessible_insert_text_cb (GtkEntry *entry, + gchar *new_text, + gint new_text_length, + gint *position) { - GtkWidget *widget; + GtkEntryAccessible *accessible; - widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (entry)); - if (gtk_entry_get_text_length (GTK_ENTRY (widget)) == 0) + if (new_text_length == 0) return; - if (entry->signal_name_insert) + accessible = GTK_ENTRY_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (entry))); + if (accessible->length_insert == 0) { - g_signal_emit_by_name (entry, - entry->signal_name_insert, - entry->position_insert, - entry->length_insert); - entry->signal_name_insert = NULL; + accessible->position_insert = *position; + accessible->length_insert = g_utf8_strlen (new_text, new_text_length); } } -/* Note arg1 returns the character at the start of the insert. - * arg2 returns the number of characters inserted. +/* We connect to GtkEditable::delete-text, since it carries + * the information we need. But we delay emitting our own + * text_changed::delete signal until the entry has update + * all its internal state and emits GtkEntry::changed. */ static void -gtk_entry_accessible_insert_text_cb (GtkEntry *entry, - gchar *arg1, - gint arg2, - gpointer arg3) +gtk_entry_accessible_delete_text_cb (GtkEntry *entry, + gint start, + gint end) { - AtkObject *accessible; - GtkEntryAccessible *entry_accessible; - gint *position = (gint *) arg3; + GtkEntryAccessible *accessible; - if (arg2 == 0) - return; - - accessible = gtk_widget_get_accessible (GTK_WIDGET (entry)); - entry_accessible = GTK_ENTRY_ACCESSIBLE (accessible); - if (!entry_accessible->signal_name_insert) + if (end < 0) { - entry_accessible->signal_name_insert = "text_changed::insert"; - entry_accessible->position_insert = *position; - entry_accessible->length_insert = g_utf8_strlen(arg1, arg2); + const gchar *text; + + text = gtk_entry_get_text (entry); + end = g_utf8_strlen (text, -1); } - /* - * The signal will be emitted when the cursor position is updated. - * or in an idle handler if it not updated. - */ - if (entry_accessible->insert_idle_handler == 0) - entry_accessible->insert_idle_handler = gdk_threads_add_idle (gtk_entry_accessible_idle_notify_insert, entry_accessible); -} -static void -gtk_entry_accessible_notify_delete (GtkEntryAccessible *entry) -{ - if (entry->signal_name_delete) + if (end == start) + return; + + accessible = GTK_ENTRY_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (entry))); + if (accessible->length_delete == 0) { - g_signal_emit_by_name (entry, - entry->signal_name_delete, - entry->position_delete, - entry->length_delete); - entry->signal_name_delete = NULL; + accessible->position_delete = start; + accessible->length_delete = end - start; } } -/* Note arg1 returns the start of the delete range, arg2 returns the - * end of the delete range if multiple characters are deleted. +/* Note the assumption here: A single ::changed emission + * will only collect a single deletion/insertion, and there + * won't be multiple insertions or deletions in a single + * change. */ static void -gtk_entry_accessible_delete_text_cb (GtkEntry *entry, - gint arg1, - gint arg2) +gtk_entry_accessible_changed_cb (GtkEntry *entry) { - AtkObject *accessible; - GtkEntryAccessible *entry_accessible; + GtkEntryAccessible *accessible; - /* - * Zero length text deleted so ignore - */ - if (arg2 - arg1 == 0) - return; + accessible = GTK_ENTRY_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (entry))); - accessible = gtk_widget_get_accessible (GTK_WIDGET (entry)); - entry_accessible = GTK_ENTRY_ACCESSIBLE (accessible); - if (!entry_accessible->signal_name_delete) + if (accessible->length_delete > 0) { - entry_accessible->signal_name_delete = "text_changed::delete"; - entry_accessible->position_delete = arg1; - entry_accessible->length_delete = arg2 - arg1; + g_signal_emit_by_name (accessible, + "text_changed::delete", + accessible->position_delete, + accessible->length_delete); + accessible->length_delete = 0; + } + if (accessible->length_insert > 0) + { + g_signal_emit_by_name (accessible, + "text_changed::insert", + accessible->position_insert, + accessible->length_insert); + accessible->length_insert = 0; } - gtk_entry_accessible_notify_delete (entry_accessible); -} - -static void -gtk_entry_accessible_changed_cb (GtkEntry *entry) -{ - /* FIXME */ } static gboolean diff --git a/gtk/a11y/gtkentryaccessible.h b/gtk/a11y/gtkentryaccessible.h index f6f606f585..211853a57e 100644 --- a/gtk/a11y/gtkentryaccessible.h +++ b/gtk/a11y/gtkentryaccessible.h @@ -39,11 +39,6 @@ struct _GtkEntryAccessible { GailWidget parent; - /* - * These fields store information about text changed - */ - gchar *signal_name_insert; - gchar *signal_name_delete; gint position_insert; gint position_delete; gint length_insert; -- 2.30.2